//===--- ExistentialCollection.swift.gyb ----------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftShims

% traversals = ['Forward', 'Bidirectional', 'RandomAccess']

@noreturn @inline(never)
internal func _abstract(_ file: StaticString = #file, line: UInt = #line) {
  fatalError("Method must be overridden", file: file, line: line)
}

//===--- Iterator ---------------------------------------------------------===//
//===----------------------------------------------------------------------===//

/// A type-erased iterator of `Element`.
///
/// This iterator forwards its `next()` method to an arbitrary underlying
/// iterator having the same `Element` type, hiding the specifics of the
/// underlying `IteratorProtocol`.
///
/// - seealso:
///   - `struct AnySequence<S : Sequence>`
public struct AnyIterator<Element> : IteratorProtocol {
  /// Create a `IteratorProtocol` instance that wraps `base` but whose type
  /// depends only on the type of `I.Element`.
  ///
  /// Example:
  ///
  ///     func digits() -> AnyIterator<String> {
  ///       let lazyStrings = (0..<10).lazy.map { String($0) }
  ///
  ///       // This is a really complicated type of no interest to our
  ///       // clients.
  ///       let iterator: MapSequenceIterator<RangeIterator<Int>, String>
  ///         = lazyStrings.makeIterator()
  ///       return AnyIterator(iterator)
  ///     }
  public // @testable
  init<I : IteratorProtocol where I.Element == Element>(_ base: I) {
    self._box = _IteratorBox(base)
  }

  /// Create a `IteratorProtocol` instance whose `next` method invokes
  /// `body` and returns the result.
  ///
  /// Example:
  ///
  ///     var x = 7
  ///     let iterator = AnyIterator { x < 15 ? x++ : nil }
  ///     let a = Array(iterator) // [ 7, 8, 9, 10, 11, 12, 13, 14 ]
  public init(body: () -> Element?) {
    self._box = _IteratorBox(_ClosureBasedIterator(body))
  }

  internal init(_box: _AnyIteratorBoxBase<Element>) {
    self._box = _box
  }

  /// Advance to the next element and return it, or `nil` if no next
  /// element exists.
  public func next() -> Element? {
    return _box.next()
  }

  internal let _box: _AnyIteratorBoxBase<Element>
}

/// Every `IteratorProtocol` can also be a `Sequence`.  Note that
/// traversing the sequence consumes the iterator.
extension AnyIterator : Sequence {}

internal struct _ClosureBasedIterator<Element> : IteratorProtocol {
  internal init(_ body: () -> Element?) {
    self._body = body
  }
  internal func next() -> Element? { return _body() }
  internal let _body: () -> Element?
}

internal class _AnyIteratorBase {}

internal class _AnyIteratorBoxBase<Element>
  : _AnyIteratorBase, IteratorProtocol {

  /// Advance to the next element and return it, or `nil` if no next
  /// element exists.
  ///
  /// - Note: Subclasses must override this method.
  internal func next() -> Element? { _abstract() }
}

internal final class _IteratorBox<
  Base : IteratorProtocol
> : _AnyIteratorBoxBase<Base.Element> {
  internal init(_ base: Base) { self._base = base }
  internal override func next() -> Base.Element? { return _base.next() }
  internal var _base: Base
}

@warn_unused_result
internal func _typeID(_ instance: AnyObject) -> ObjectIdentifier {
  return ObjectIdentifier(instance.dynamicType)
}

//===--- Sequence ---------------------------------------------------------===//
//===----------------------------------------------------------------------===//

internal class _AnySequenceBox<Element> {
  internal func makeIterator() -> AnyIterator<Element> { _abstract() }

  internal var _underestimatedCount: Int { _abstract() }

  internal func _copyContents(initializing ptr: UnsafeMutablePointer<Element>)
    -> UnsafeMutablePointer<Element> {
    _abstract()
  }
  internal func _copyToNativeArrayBuffer() -> _ContiguousArrayStorageBase {
    _abstract()
  }

  internal func _dropFirst(_ n: Int) -> _AnySequenceBox<Element> { _abstract() }
  internal func _prefix(_ maxLength: Int) -> _AnySequenceBox<Element> {
    _abstract()
  }
}

internal class _AnyCollectionBoxBase<Element> : _AnySequenceBox<Element> {
  internal init(
    startIndex: _ForwardIndexBoxProtocol, endIndex: _ForwardIndexBoxProtocol
  ) {
    self.startIndex = startIndex
    self.endIndex = endIndex
  }
  internal let startIndex: _ForwardIndexBoxProtocol
  internal let endIndex: _ForwardIndexBoxProtocol
}

% for Kind in ['Sequence', 'Collection']:
// FIXME: can't make this a protocol due to <rdar://20209031>
internal final class _${Kind}Box<
  S : ${Kind}
%   if Kind == 'Sequence':
  where
    S.SubSequence : ${Kind},
    S.SubSequence.Iterator.Element == S.Iterator.Element,
    S.SubSequence.SubSequence == S.SubSequence
%   end
> : _Any${Kind}Box<S.Iterator.Element> {
  typealias Element = S.Iterator.Element

  override func makeIterator() -> AnyIterator<Element> {
    return AnyIterator(_base.makeIterator())
  }
  override var _underestimatedCount: Int {
    return _base.underestimatedCount
  }
  override func _copyContents(initializing ptr: UnsafeMutablePointer<Element>)
    -> UnsafeMutablePointer<Element> {
    return _base._copyContents(initializing: ptr)
  }
  override func _copyToNativeArrayBuffer() -> _ContiguousArrayStorageBase {
    return _base._copyToNativeArrayBuffer()._storage
  }
%   if Kind == 'Sequence':
  internal override func _dropFirst(_ n: Int) -> _AnySequenceBox<Element> {
    return _SequenceBox<S.SubSequence>(_base.dropFirst(n))
  }
  internal override func _prefix(_ maxLength: Int) -> _AnySequenceBox<Element> {
    return _SequenceBox<S.SubSequence>(_base.prefix(maxLength))
  }
%   end

%   if Kind == 'Collection':
  override func _count() -> IntMax {
    return numericCast(_base.count)
  }
  override subscript(position: _ForwardIndexBoxProtocol) -> Element {
    if let i = position._unbox() as S.Index? {
      return _base[i]
    }
    fatalError("Index type mismatch!")
  }
  init(
    _ base: S,
    startIndex: _ForwardIndexBoxProtocol,
    endIndex: _ForwardIndexBoxProtocol
  ) {
    self._base = base
    super.init(startIndex: startIndex, endIndex: endIndex)
  }
%   else:
  init(_ base: S) {
    self._base = base
  }
%   end
  internal var _base: S
}
% end

internal struct _ClosureBasedSequence<Iterator : IteratorProtocol>
  : Sequence {

  internal init(_ makeUnderlyingIterator: () -> Iterator) {
    self._makeUnderlyingIterator = makeUnderlyingIterator
  }

  internal func makeIterator() -> Iterator {
    return _makeUnderlyingIterator()
  }

  internal var _makeUnderlyingIterator: () -> Iterator
}

/// A type-erased sequence.
///
/// Forwards operations to an arbitrary underlying sequence having the
/// same `Element` type, hiding the specifics of the underlying
/// `Sequence`.
///
/// - SeeAlso: `AnyIterator<Element>`.
public struct AnySequence<Element> : Sequence {
  @available(*, unavailable, renamed: "Element")
  public typealias T = Element

  /// Wrap and forward operations to `base`.
  public init<
    S: Sequence
    where
      S.Iterator.Element == Element,
      S.SubSequence : Sequence,
      S.SubSequence.Iterator.Element == Element,
      S.SubSequence.SubSequence == S.SubSequence
  >(_ base: S) {
    _box = _SequenceBox(base)
  }

  /// Create a sequence whose `makeIterator()` method forwards to
  /// `makeUnderlyingIterator`.
  public init<I : IteratorProtocol where I.Element == Element>(
    _ makeUnderlyingIterator: () -> I
  ) {
    self.init(_ClosureBasedSequence(makeUnderlyingIterator))
  }

  internal init(_ box: _AnySequenceBox<Element>) {
    _box = box
  }

  /// Returns an iterator over the elements of this sequence.
  ///
  /// - Complexity: O(1).
  public func makeIterator() -> AnyIterator<Element> {
    return _box.makeIterator()
  }

  internal let _box: _AnySequenceBox<Element>
}

extension AnySequence {
  @warn_unused_result
  public func dropFirst(_ n: Int) -> AnySequence<Element> {
    return AnySequence(_box._dropFirst(n))
  }

  @warn_unused_result
  public func prefix(_ maxLength: Int) -> AnySequence<Element> {
    return AnySequence(_box._prefix(maxLength))
  }
}

% for Kind in ['Sequence'] + [t + 'Collection' for t in traversals]:
extension Any${Kind} {
  public var underestimatedCount: Int {
    return _box._underestimatedCount
  }

  public func _copyContents(initializing ptr: UnsafeMutablePointer<Element>)
    -> UnsafeMutablePointer<Element> {
    return _box._copyContents(initializing: ptr)
  }

  public func _copyToNativeArrayBuffer() -> _ContiguousArrayBuffer<Element> {
    return _ContiguousArrayBuffer(self._box._copyToNativeArrayBuffer())
  }
}

% end

//===--- ForwardIndex -----------------------------------------------------===//
//===----------------------------------------------------------------------===//

internal protocol _ForwardIndexBoxProtocol : class {
  var typeID: ObjectIdentifier { get }

  @warn_unused_result
  func successor() -> _ForwardIndexBoxProtocol

  func _successorInPlace()

  @warn_unused_result
  func equals(_ other: _ForwardIndexBoxProtocol) -> Bool

  @warn_unused_result
  func _unbox<T : ForwardIndex>() -> T?

  @warn_unused_result
  func _distance(to other: _ForwardIndexBoxProtocol) -> AnyForwardIndex.Distance

  // FIXME: Can't return Self from _advanced(by:) pending <rdar://20181253>
  @warn_unused_result
  func _advanced(by distance: AnyForwardIndex.Distance) -> _ForwardIndexBoxProtocol

  @warn_unused_result
  func _advanced(
    by distance: AnyForwardIndex.Distance,
    limit: _ForwardIndexBoxProtocol
  ) -> _ForwardIndexBoxProtocol
}

internal class _ForwardIndexBox<
  BaseIndex: ForwardIndex
> : _ForwardIndexBoxProtocol {
  required init(_ base: BaseIndex) {
    self.base = base
  }

  func successor() -> _ForwardIndexBoxProtocol {
    return self.dynamicType.init(self.base.successor())
  }

  func _successorInPlace() {
    self.base._successorInPlace()
  }

  func unsafeUnbox(_ other: _ForwardIndexBoxProtocol) -> BaseIndex {
    return unsafeDowncast(other, to: _ForwardIndexBox.self).base
  }

  func equals(_ other: _ForwardIndexBoxProtocol) -> Bool {
    return base == unsafeUnbox(other)
  }

  func _distance(to other: _ForwardIndexBoxProtocol) -> AnyForwardIndex.Distance {
    return numericCast(base.distance(to: unsafeUnbox(other)))
  }

  func _advanced(by n: AnyForwardIndex.Distance) -> _ForwardIndexBoxProtocol {
    return self.dynamicType.init(base.advanced(by: numericCast(n)))
  }

  func _advanced(
    by n: AnyForwardIndex.Distance,
    limit: _ForwardIndexBoxProtocol
  ) -> _ForwardIndexBoxProtocol {
    return self.dynamicType.init(
      base.advanced(by: numericCast(n), limit: unsafeUnbox(limit)))
  }

  func _unbox<T : ForwardIndex>() -> T? {
    if T.self is BaseIndex.Type {
      _sanityCheck(BaseIndex.self is T.Type)
      // This bit cast is really nothing as we have proven they are
      // the same type.
      return unsafeBitCast(base, to: T.self)
    }
    return nil
  }

  var typeID: ObjectIdentifier { return _typeID(self) }

  internal // private
  var base: BaseIndex
}

//===--- BidirectionalIndex -----------------------------------------------===//
//===----------------------------------------------------------------------===//

internal protocol _BidirectionalIndexBoxProtocol : _ForwardIndexBoxProtocol {
  func predecessor() -> _BidirectionalIndexBoxProtocol
  func _predecessorInPlace()
}

internal class _BidirectionalIndexBox<
  BaseIndex: BidirectionalIndex
> : _ForwardIndexBox<BaseIndex>, _BidirectionalIndexBoxProtocol {
  required init(_ base: BaseIndex) {
    super.init(base)
  }

  override func successor() -> _ForwardIndexBoxProtocol {
    return self.dynamicType.init(self.base.successor())
  }

  func predecessor() -> _BidirectionalIndexBoxProtocol {
    return self.dynamicType.init(self.base.predecessor())
  }

  func _predecessorInPlace() {
    self.base._predecessorInPlace()
  }
}

//===--- RandomAccessIndex ------------------------------------------------===//
//===----------------------------------------------------------------------===//

internal protocol _RandomAccessIndexBoxProtocol : _BidirectionalIndexBoxProtocol {}

internal final class _RandomAccessIndexBox<
  BaseIndex: RandomAccessIndex
> : _BidirectionalIndexBox<BaseIndex>, _RandomAccessIndexBoxProtocol {
  required init(_ base: BaseIndex) {
    super.init(base)
  }
}

//===--- All Index Protocols ----------------------------------------------===//
//===----------------------------------------------------------------------===//

% for Traversal in traversals:

%   Self = 'Any%sIndex' % Traversal
/// A wrapper over an underlying `${Traversal}Index` that hides
/// the specific underlying type.
///
/// - SeeAlso: `Any${Traversal}Collection`
public struct ${Self} : ${Traversal}Index {
  public typealias Distance = IntMax

  /// Wrap and forward operations to `base`.
  public init<BaseIndex : ${Traversal}Index>(_ base: BaseIndex) {
    _box = _${Traversal}IndexBox(base)
  }

  /// Returns the next consecutive value in a discrete sequence of
  /// `${Self}` values.
  ///
  /// - Precondition: `self` has a well-defined successor.
  public func successor() -> ${Self} {
    return ${Self}(_box.successor())
  }

  public mutating func _successorInPlace() {
    if _fastPath(_isUnique_native(&_box)) {
      _box._successorInPlace()
    }
    else {
      self = successor()
    }
  }

  % if Traversal != 'Forward':
  /// Returns the previous consecutive value in a discrete sequence of
  /// `${Self}` values.
  ///
  /// - Precondition: `self` has a well-defined predecessor.
  public func predecessor() -> ${Self} {
    return ${Self}(_box.predecessor())
  }

  public mutating func _predecessorInPlace() {
    if _fastPath(_isUnique_native(&_box)) {
      _box._predecessorInPlace()
    }
    else {
      self = predecessor()
    }
  }
  % end

  % if Traversal == 'RandomAccess':
  public func distance(to other: ${Self}) -> Distance {
    return _box._distance(to: other._box)
  }

  public func advanced(by amount: Distance) -> ${Self} {
    return ${Self}(_box._advanced(by: amount))
  }

  public func advanced(by amount: Distance, limit: ${Self}) -> ${Self} {
    return ${Self}(_box._advanced(by: amount, limit: limit._box))
  }
  % end

  //===--- private --------------------------------------------------------===//

  internal var _typeID: ObjectIdentifier {
    return _box.typeID
  }

  internal init(_ box: _ForwardIndexBoxProtocol) {
    self._box = box${
      '' if Traversal == 'Forward' else ' as! _%sIndexBoxProtocol' % Traversal}
  }

  // _box is passed inout to _isUnique.  Although its value
  // is unchanged, it must appear mutable to the optimizer.
  internal var _box: _${Traversal}IndexBoxProtocol

  public func _distance(to other: ${Self}) -> ${Self}.Distance {
    precondition(
      self._typeID == other._typeID,
      "distance: base index types differ.")
    return self._box._distance(to: other._box)
  }
}

/// Returns `true` iff `lhs` and `rhs` wrap equal underlying
/// `${Self}`s.
///
/// - Precondition: The types of indices wrapped by `lhs` and `rhs` are
///   identical.
@warn_unused_result
public func == (lhs: ${Self}, rhs: ${Self}) -> Bool {
  precondition(lhs._typeID == rhs._typeID, "base index types differ.")
  return lhs._box.equals(rhs._box)
}
% end

//===--- Collections ------------------------------------------------------===//
//===----------------------------------------------------------------------===//

internal class _AnyCollectionBox<Element> : _AnyCollectionBoxBase<Element> {
  internal subscript(_: _ForwardIndexBoxProtocol) -> Element { _abstract() }
  internal func _count() -> IntMax { _abstract() }

  // FIXME: should be inherited, but a known bug prevents it since
  // this class is generic.
  internal override init(
    startIndex: _ForwardIndexBoxProtocol,
    endIndex: _ForwardIndexBoxProtocol
  ) {
    super.init(startIndex: startIndex, endIndex: endIndex)
  }
}

/// A protocol for `AnyForwardCollection<Element>`,
/// `AnyBidirectionalCollection<Element>`, and
/// `AnyRandomAccessCollection<Element>`.
///
/// This protocol can be considered an implementation detail of the
/// `===` and `!==` implementations for these types.
public protocol AnyCollectionProtocol : Collection {
  /// Identifies the underlying collection stored by `self`. Instances
  /// copied from one another have the same `_underlyingCollectionID`.
  var _underlyingCollectionID: ObjectIdentifier { get }
}

/// Returns `true` iff `lhs` and `rhs` store the same underlying collection.
@warn_unused_result
public func === <
  L : AnyCollectionProtocol, R : AnyCollectionProtocol
>(lhs: L, rhs: R) -> Bool {
  return lhs._underlyingCollectionID == rhs._underlyingCollectionID
}

/// Returns `false` iff `lhs` and `rhs` store the same underlying collection.
@warn_unused_result
public func !== <
  L : AnyCollectionProtocol, R : AnyCollectionProtocol
>(lhs: L, rhs: R) -> Bool {
  return lhs._underlyingCollectionID != rhs._underlyingCollectionID
}

% for (ti, Traversal) in enumerate(traversals):
/// A type-erased wrapper over any collection with indices that
/// support ${Traversal.lower().replace('omacc', 'om acc')} traversal.
///
/// Forwards operations to an arbitrary underlying collection having the
/// same `Element` type, hiding the specifics of the underlying
/// `Collection`.
///
/// - SeeAlso: ${', '.join('`Any%sType`' % t for t in (2 * traversals)[ti + 1 : ti + 3]) }
public struct Any${Traversal}Collection<Element> : AnyCollectionProtocol {
  typealias Box = _AnyCollectionBox<Element>

%   for SubTraversal in traversals[ti:]:
  /// Create an `Any${Traversal}Collection` that stores `base` as its
  /// underlying collection.
  ///
  /// - Complexity: O(1).
  public init<
    C : Collection
    where
    C.Index : ${SubTraversal}Index, C.Iterator.Element == Element
  >(_ base: C) {
    self._box = _CollectionBox<C>(
      base,
      startIndex: _${SubTraversal}IndexBox(base.startIndex),
      endIndex: _${SubTraversal}IndexBox(base.endIndex))
  }

  /// Create an `Any${Traversal}Collection` having the same underlying
  /// collection as `other`.
  ///
  /// - Postcondition: The result is `===` to `other`.
  ///
  /// - Complexity: O(1).
  public init(_ other: Any${SubTraversal}Collection<Element>) {
    self._box = other._box
  }
%   end

%   for SuperTraversal in traversals[:ti]:
  /// If the indices of the underlying collection stored by `other`
  /// satisfy `${Traversal}Index`, create an
  /// `Any${Traversal}Collection` having the same underlying
  /// collection as `other`.  Otherwise, the result is `nil`.
  ///
  /// - Complexity: O(1).
  public init?(_ other: Any${SuperTraversal}Collection<Element>) {
    if !(other._box.startIndex is _${Traversal}IndexBoxProtocol) {
      return nil
    }
    _sanityCheck(other._box.endIndex is _${Traversal}IndexBoxProtocol)
    self._box = other._box
  }
%   end

  /// Returns an iterator over the elements of this collection.
  ///
  /// - Complexity: O(1).
  public func makeIterator() -> AnyIterator<Element> {
    return _box.makeIterator()
  }

  /// The position of the first element in a non-empty collection.
  ///
  /// In an empty collection, `startIndex == endIndex`.
  public var startIndex: Any${Traversal}Index {
    return Any${Traversal}Index(_box.startIndex)
  }

  /// The collection's "past the end" position.
  ///
  /// `endIndex` is not a valid argument to `subscript`, and is always
  /// reachable from `startIndex` by zero or more applications of
  /// `successor()`.
  public var endIndex: Any${Traversal}Index {
    return Any${Traversal}Index(_box.endIndex)
  }

  /// Access the element indicated by `position`.
  ///
  /// - Precondition: `position` indicates a valid position in `self` and
  ///   `position != endIndex`.
  public subscript(position: Any${Traversal}Index) -> Element {
    return _box[position._box]
  }

  /// The number of elements.
  ///
  /// - Complexity: ${'O(1)' if Traversal == 'RandomAccess' else 'O(N)'}.
  public var count: IntMax {
    return _box._count()
  }

  /// Uniquely identifies the stored underlying collection.
  public // Due to language limitations only
  var _underlyingCollectionID: ObjectIdentifier {
    return ObjectIdentifier(_box)
  }

  internal let _box: Box
}
% end

@available(*, unavailable, renamed: "AnyIterator")
public struct AnyGenerator<Element> {}

extension AnyIterator {
  @available(*, unavailable, renamed: "makeIterator")
  public func generate() -> AnyIterator<Element> {
    fatalError("unavailable function can't be called")
  }
}

% for Kind in ['Sequence'] + [t + 'Collection' for t in traversals]:
extension Any${Kind} {

  @available(*, unavailable, message: "Please use underestimatedCount property instead.")
  public var underestimateCount: Int {
    fatalError("unavailable function can't be called")
  }
}
%end

@available(*, unavailable, renamed: "AnyCollectionProtocol")
public typealias AnyCollectionType = AnyCollectionProtocol

extension AnyCollectionProtocol {
  @available(*, unavailable, renamed: "makeIterator")
  public func generate() -> AnyIterator<Iterator.Element> {
    fatalError("unavailable function can't be called")
  }
}
